/**
 * client.c
 *
 * Connects to server with given IP address over port 8080.  
 * Once this connection is made image data is received and 
 * stored into a jpg file.
 *
 * @author Team Wire-Lettuce
 * @date 12 Apr 2011
 *
 * usage: client hostname
 */

#include "camera.h"

int main(int argc, char *argv[])
{
  int sockfd, numbytes, rv, i, XMIT_state;  
  unsigned char buf[NUM_BYTES];
  char buf2[0];
  struct addrinfo hints, *servinfo, *p;
  char s[INET6_ADDRSTRLEN];
  
  char onesCount = '0';       // ones counter for file name
  char tensCount = '0';       // tens counter for file name
  char hundCount = '0';       // hundreds counter for file name
  char thousCount = '0';      // thousands counter for file name
  char tenThousCount = '0';   // ten thousands counter for file name
  
  // check # arguments
  if (argc != 2) {
    fprintf(stderr,"usage: client hostname\n");
    exit(1);
  }

  // initialize file name to image00000
  char fileName[15] = {"image00000.jpg"};
  
  // initialize file pointer to file we are storing the pictures in
  FILE* jpgFile;
  	
  // client setup
  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;

  // get address info for connection
  if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    return SUCCESS;
  }

  // loop through all the results and connect to the first we can
  for(p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype,
			 p->ai_protocol)) == -1) {
      perror("client: socket");
      continue;
    }

    if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
      close(sockfd);
      perror("client: connect");
      continue;
    }

    break;
  }

  // if connection failed
  if (p == NULL) {
    fprintf(stderr, "client: failed to connect\n");
    return SUCCESS;
  }

  // connect
  inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
	    s, sizeof s);

  freeaddrinfo(servinfo); // all done with this structure

  
    
  while(1){

    // reset XMIT_state to true
    XMIT_state = TRUE;

    // counts to 99,999 in ASCII using five character variables
    // to dynamically set the file name for the jpg after each
    // picture is taken.  ':' is the character after '9' so it
    // represents when to tick the next counter and to reset the previous
    // counters
    if ((onesCount+1) == ':')
      {
	tensCount++;
	onesCount = '0';

	if((tensCount) == ':')
	  {
	    hundCount++;
	    onesCount = '0';
	    tensCount = '0';

	    if((hundCount)== ':')
	      {
		thousCount++;
		onesCount = '0';
		tensCount = '0';
		hundCount = '0';
	      

		if((thousCount) == ':')
		  {
		    tenThousCount++;
		    onesCount = '0';
		    tensCount = '0';
		    hundCount = '0';
		    thousCount = '0';
		  }
	      }
	  }
      }
    else
      {
	onesCount++;
      }
         

        
    // set the file name to the appropriate number
    fileName[9] = onesCount;
    fileName[8] = tensCount;
    fileName[7] = hundCount;
    fileName[6] = thousCount;
    fileName[5] = tenThousCount;
	
    // open the file
    jpgFile = fopen(fileName, "w");
    if (jpgFile == NULL)
      {
	perror("ERR: Client fopen");
	return ERROR;
      }
      
    
    
    // loop until we reach the end of the file denoted by
    // JPG format
    while(XMIT_state == TRUE)
      {
	int count = 0;
	// recieve bytes from server and store into buffer
	// NUM_BYTES is greater than the size of the image
	if ((numbytes = recv(sockfd, buf, NUM_BYTES, 0)) == -1) 
	  {
	    perror("recv");
	    exit(ERROR);
	  }
      	  
	// write the image to the jpg file until we receive 0xFF 0xD9
	for(i = 0; i < numbytes; i++)
	  {
	    buf2[0] = buf[i];
	    
	    if((buf[i] == 0xD9) && (buf[i - 1] == 0xFF))
	      XMIT_state = FALSE;
		
	    if(fwrite(buf2, 1, NUM_CHUNKS, jpgFile) == errno)
	      {
		perror("ERR: fwrite");
		return ERROR;
	      }
	    
	  }
	
	    	  
      }// while(XMIT_state == TRUE)

    fclose(jpgFile);
    
  }// while(1)

  close(sockfd);

  return SUCCESS;
}

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
	if (sa->sa_family == AF_INET) {
		return &(((struct sockaddr_in*)sa)->sin_addr);
	}

	return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
